package com.zq.behavior.duty_chain;

import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * 责任链
 * @param <T> 数据类型
 * @param <H> 子类类型
 */
public abstract class Handler<T, H extends Handler<T, H>> {
    protected final Predicate<T> predicate;
    protected final Consumer<T> consumer;
    protected H next;

    protected Handler(Predicate<T> predicate, Consumer<T> consumer) {
        this.predicate = Objects.requireNonNull(predicate);
        this.consumer = Objects.requireNonNull(consumer);
    }

    /**
     * 使用建造者将分离构建与执行
     * @param <T> 数据类型
     * @param <B> 子类建造者
     * @param <H> 子类责任链
     */
    static abstract class Builder<T, B extends Builder<T, B, H>, H extends Handler<T, H>> {
        private H head;
        private H rear;

        public B add(Predicate<T> predicate, Consumer<T> consumer) {
            Objects.requireNonNull(predicate);
            Objects.requireNonNull(consumer);
            H handler = create(predicate, consumer);

            if (head == null) {
                head = rear = handler;
                return self();
            }

            rear.next = handler;
            rear = handler;

            return self();
        }

        public void clear() {
            H p, q;
            p = head;

            while (p.next != null) {
                q = p.next;
                p.next = null;
                p = q;
            }

            head = rear = null;
        }

        abstract protected B self();

        abstract protected H create(Predicate<T> predicate, Consumer<T> consumer);

        public H build() {
            return head;
        }
    }

    abstract protected void handle(T t);
}

final class OnlyOnceHandler<T> extends Handler<T, OnlyOnceHandler<T>> {

    static final class Builder<T> extends Handler.Builder<T, Builder<T>, OnlyOnceHandler<T>> {
        @Override
        protected Builder<T> self() {
            return this;
        }

        @Override
        protected OnlyOnceHandler<T> create(Predicate<T> predicate, Consumer<T> consumer) {
            return new OnlyOnceHandler<>(predicate, consumer);
        }
    }

    private OnlyOnceHandler(Predicate<T> predicate, Consumer<T> consumer) {
        super(predicate, consumer);
    }

    @Override
    public void handle(T t) {
        if (predicate.test(t)) {
            consumer.accept(t);
            return;
        }

        if (next != null) {
            next.handle(t);
        }
    }
}

final class AllHandler<T> extends Handler<T, AllHandler<T>> {

    static final class Builder<T> extends Handler.Builder<T, Builder<T>, AllHandler<T>> {
        @Override
        protected Builder<T> self() {
            return this;
        }

        @Override
        protected AllHandler<T> create(Predicate<T> predicate, Consumer<T> consumer) {
            return new AllHandler<>(predicate, consumer);
        }
    }

    private AllHandler(Predicate<T> predicate, Consumer<T> consumer) {
        super(predicate, consumer);
    }

    @Override
    public void handle(T t) {
        if (predicate.test(t)) {
            consumer.accept(t);
        }

        if (next != null) {
            next.handle(t);
        }
    }
}